package com.maserb.monitor.service.schoolConduct.impl;

import com.maserb.monitor.entity.JwOrgEntity;
import com.maserb.monitor.entity.UserEntity;
import com.maserb.monitor.entity.schoolConduct.SchoolConductItemEntity;
import com.maserb.monitor.entity.schoolConduct.StudentConductRecordEntity;
import com.maserb.monitor.entity.schoolForum.PostEntity;
import com.maserb.monitor.entity.schoolOrg.SchoolUserOrgEntity;
import com.maserb.monitor.entity.schoolStudent.SchoolStudentEntity;
import com.maserb.monitor.entity.schoolStudent.StudentScoreEntity;
import com.maserb.monitor.repository.schoolConduct.StudentConductRecordRepository;
import com.maserb.monitor.repository.schoolOrg.SchoolUserOrgRepository;
import com.maserb.monitor.repository.schoolStudent.SchoolStudentRepository;
import com.maserb.monitor.service.author_manage.UserService;
import com.maserb.monitor.service.base.IToolService;
import com.maserb.monitor.service.base.impl.JpaSpecificationServiceImpl;
import com.maserb.monitor.service.jwEducation.JwOrgService;
import com.maserb.monitor.service.schoolConduct.SchoolConductItemService;
import com.maserb.monitor.service.schoolConduct.StudentConductRecordService;
import com.maserb.monitor.service.schoolStudent.SchoolStudentService;
import org.apache.catalina.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
import org.thymeleaf.util.StringUtils;

import javax.persistence.criteria.*;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

@Service
public class StudentConductRecordServiceImpl extends JpaSpecificationServiceImpl<StudentConductRecordRepository,
        StudentConductRecordRepository, StudentConductRecordEntity, String>
        implements StudentConductRecordService {

    @Autowired
    StudentConductRecordRepository studentConductRecordRepository;

    @Autowired
    SchoolStudentRepository studentRepository;

    @Autowired
    IToolService toolService;

    @Autowired
    SchoolConductItemService itemService;

    @Autowired
    UserService userService;

    @Autowired
    JwOrgService orgService;

    @Autowired
    SchoolStudentService studentService;

    @Autowired
    SchoolUserOrgRepository userOrgRepository;

    @Override
    public List<StudentConductRecordEntity> findByStudent(String studentId) {
        return studentConductRecordRepository.findByStudentId(studentId);
    }

    @Override
    public Page<StudentConductRecordEntity> findAll(Pageable pageable, String studentId) {
        return this.findAll(getSpecification(studentId),pageable);
    }

    @Override
    public Page<StudentConductRecordEntity> findAll(Pageable pageable,String userId, String name, String studentId, String clazzId, String itemId, String startTime, String endTime) {

        UserEntity user = new UserEntity();
        List<JwOrgEntity> orgList = new ArrayList<JwOrgEntity>();
        List<String>orgIdList = new ArrayList<String>();
        if(!StringUtils.isEmptyOrWhitespace(userId)){
            user = userService.findOne(userId);
            if(null!=user &&!"".equals( user.getId())){
                orgList = orgService.findByUser(user);
                if(orgList.size()>0){
                    for(JwOrgEntity org:orgList){
                        orgIdList.add(org.getId());
                    }
                }
            }
        }
        return this.findAll(getSpecificationByName( orgIdList,name, studentId, clazzId, itemId, startTime, endTime),pageable);
    }

    @Override
    public void saveConduct(StudentConductRecordEntity record) {
        studentConductRecordRepository.save(record);
/*
        SchoolStudentEntity student = record.getStudent();
        student.setConductScore(student.getConductScore() + record.getItem().getScore().intValue());

        studentRepository.save(student);*/
    }

    private Specification<StudentConductRecordEntity> getSpecification(String studentId){
        return new Specification<StudentConductRecordEntity>() {
            @Override
            public Predicate toPredicate(Root<StudentConductRecordEntity> root, CriteriaQuery<?> criteriaQuery, CriteriaBuilder criteriaBuilder) {
                /*Join<StudentConductRecordEntity, SchoolStudentEntity> join = root.join("student", JoinType.LEFT);
                Path<String> pathJoinStudent = join.get("id");*/
                Path<String> pathStatus = root.get("status");
                Path<SchoolStudentEntity>pathStudent = root.get("student");
                ArrayList<Predicate> list = new ArrayList<Predicate>();
                /*list.add(criteriaBuilder.and(criteriaBuilder.equal(pathJoinStudent, root.get("student"))));*/
                list.add(criteriaBuilder.and(criteriaBuilder.equal(pathStatus, "1")));
                if(!StringUtils.isEmptyOrWhitespace(studentId)){
                    SchoolStudentEntity studentEntity = studentService.findOne(studentId);
                    if(null!=studentEntity && !StringUtils.isEmptyOrWhitespace(studentEntity.getId())){
                        list.add(criteriaBuilder.and(criteriaBuilder.equal(pathStudent, studentEntity)));
                    }
                }
               /* return criteriaBuilder.and(list.toArray(new Predicate[list.size()]));*/
                return criteriaBuilder.and(list.toArray(new Predicate[list.size()]));
            }
        };
    }

    private Specification<StudentConductRecordEntity> getSpecificationByName(List<String> orgIdList,String name, String studentId, String clazzId, String itemId, String startTime, String endTime){
        return new Specification<StudentConductRecordEntity>() {
            @Override
            public Predicate toPredicate(Root<StudentConductRecordEntity> root, CriteriaQuery<?> criteriaQuery, CriteriaBuilder criteriaBuilder) {
                ArrayList<Predicate> list = new ArrayList<Predicate>();
                Join<StudentConductRecordEntity, SchoolStudentEntity> joinStudent = root.join("student", JoinType.LEFT);
                Path<String> pathJoinStudent = joinStudent.get("id");
                Path<String> pathJoinStudentName = joinStudent.get("name");
                Path<String> pathJoinStudentId = joinStudent.get("studentId");
                Path<String> pathJoinStudentOrgId = joinStudent.get("orgId");
                list.add(criteriaBuilder.and(criteriaBuilder.equal(pathJoinStudent, root.get("student"))));
                Path<String> pathItem = root.get("item");
                Path<Date> pathCreateTime = root.get("createTime");
                if (null!=orgIdList && orgIdList.size()>0) {
                    Expression<String> exp = pathJoinStudentOrgId;
                    list.add(exp.in(orgIdList));
                }
                if (!StringUtils.isEmptyOrWhitespace(name)) {
                    list.add(criteriaBuilder.and(criteriaBuilder.like(pathJoinStudentName, "%"+name+"%")));
                }
                if (!StringUtils.isEmptyOrWhitespace(clazzId)) {
                    list.add(criteriaBuilder.and(criteriaBuilder.equal(pathJoinStudentOrgId, clazzId)));
                }
                if (!StringUtils.isEmptyOrWhitespace(studentId)) {
                    list.add(criteriaBuilder.and(criteriaBuilder.equal(pathJoinStudentId, studentId)));
                }
                if (!StringUtils.isEmptyOrWhitespace(itemId)) {
                    SchoolConductItemEntity itemEntity = itemService.findOne(itemId);
                    if(null!=itemEntity){
                        list.add(criteriaBuilder.and(criteriaBuilder.equal(pathItem, itemEntity)));
                    }
                }
                if(!StringUtils.isEmptyOrWhitespace(startTime)) {
                    list.add(criteriaBuilder.and(criteriaBuilder.greaterThanOrEqualTo(pathCreateTime, toolService.parseDateFromNormalDateFormat(startTime))));
                }
                if(!StringUtils.isEmptyOrWhitespace(endTime)) {
                    list.add(criteriaBuilder.and(criteriaBuilder.lessThanOrEqualTo(pathCreateTime, toolService.parseDateFromNormalDateFormat(endTime))));
                }
                return criteriaBuilder.and(list.toArray(new Predicate[list.size()]));
            }
        };
    }

    @Override
    public void doReview(StudentConductRecordEntity entity) {
        SchoolStudentEntity student = entity.getStudent();
        student.setConductScore(student.getConductScore() + entity.getItem().getScore().intValue());
        studentRepository.save(student);
        entity.setStatus("1");
        this.save(entity);
    }

    @Override
    public void doNotReview(StudentConductRecordEntity entity) {
        /*SchoolStudentEntity student = entity.getStudent();
        student.setConductScore(student.getConductScore() + entity.getItem().getScore().intValue());
        studentRepository.save(student);*/
        entity.setStatus("2");
        this.save(entity);
    }
}